package com.bestcem.xm.common.core.uitls;

import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.io.ByteArrayInputStream;
import java.util.*;

@Slf4j
public class DynamicEasyExcelImportUtil {

    /**
     * 动态获取全部列和数据体
     *
     * @param stream         excel文件流
     * @param parseRowNumber 指定读取行
     * @return List<JSONObject>
     */
    public static List<Map<String, String>> parseExcelToView(byte[] stream, Integer parseRowNumber) {
        DynamicEasyExcelListener readListener = new DynamicEasyExcelListener();
        EasyExcelFactory.read(new ByteArrayInputStream(stream)).registerReadListener(readListener).headRowNumber(parseRowNumber).sheet(0).doRead();
        List<Map<Integer, String>> headList = readListener.getHeadList();
        if (CollectionUtils.isEmpty(headList)) {
            throw new RuntimeException("Excel未包含表头");
        }
        List<Map<Integer, String>> dataList = readListener.getDataList();
        if (CollectionUtils.isEmpty(dataList)) {
            throw new RuntimeException("Excel未包含数据");
        }
        //获取头部,取最后一次解析的列头数据
        Map<Integer, String> excelHeadIdxNameMap = headList.get(headList.size() - 1);
        //封装数据体
        List<Map<String, String>> excelDataList = Lists.newArrayList();
        for (Map<Integer, String> dataRow : dataList) {
            Map<String, String> rowData = new LinkedHashMap<>();
            excelHeadIdxNameMap.forEach((key, value) -> rowData.put(value, dataRow.get(key)));
            excelDataList.add(rowData);
        }
        return excelDataList;
    }

    /**
     * 动态获取全部列和数据体
     *
     * @param stream          excel文件流
     * @param parseRowNumber  指定读取行
     * @param headColumnBiMap 表头映射
     * @return List<Map < String, String>>
     */
    public static List<Map<String, String>> parseExcelToView(byte[] stream, Integer parseRowNumber, HashBiMap<String, String> headColumnBiMap) {
        DynamicEasyExcelListener readListener = new DynamicEasyExcelListener();
        EasyExcelFactory.read(new ByteArrayInputStream(stream)).registerReadListener(readListener).headRowNumber(parseRowNumber).sheet(0).doRead();
        List<Map<Integer, String>> headList = readListener.getHeadList();
        if (CollectionUtils.isEmpty(headList)) {
            throw new RuntimeException("Excel未包含表头");
        }
        List<Map<Integer, String>> dataList = readListener.getDataList();
        if (CollectionUtils.isEmpty(dataList)) {
            throw new RuntimeException("Excel未包含数据");
        }
        //用value获取key
        BiMap<String, String> headkeymap = headColumnBiMap.inverse();
        //获取头部,取最后一次解析的列头数据
        Map<Integer, String> excelHeadIdxNameMap = headList.get(headList.size() - 1);
        //封装数据体
        List<Map<String, String>> excelDataList = Lists.newArrayList();
        for (Map<Integer, String> dataRow : dataList) {
            Map<String, String> rowData = new LinkedHashMap<>();
            excelHeadIdxNameMap.forEach((key, value) -> rowData.put(headkeymap.get(value), dataRow.get(key)));
            excelDataList.add(rowData);
        }
        return excelDataList;
    }

    public static class DynamicEasyExcelListener extends AnalysisEventListener<Map<Integer, String>> {
        /**
         * 表头数据（存储所有的表头数据）
         */
        private final List<Map<Integer, String>> headList = new ArrayList<>();
        /**
         * 数据体
         */
        private final List<Map<Integer, String>> dataList = new ArrayList<>();

        /**
         * 这里会一行行的返回头
         */
        @Override
        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
            //log.info("解析到一条头数据:{}", JSON.toJSONString(headMap));
            //存储全部表头数据
            headList.add(headMap);
        }

        /**
         * 这个每一条数据解析都会来调用
         */
        @Override
        public void invoke(Map<Integer, String> data, AnalysisContext context) {
            //log.info("解析到一条数据:{}", JSON.toJSONString(data));
            dataList.add(data);
        }

        /**
         * 所有数据解析完成了 都会来调用
         */
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            // 这里也要保存数据，确保最后遗留的数据也存储到数据库
            //log.info("所有数据解析完成！");
        }

        public List<Map<Integer, String>> getHeadList() {
            return headList;
        }

        public List<Map<Integer, String>> getDataList() {
            return dataList;
        }
    }

    public static class EasyExcelListener<T> extends AnalysisEventListener<T> {

        private final List<T> data = new LinkedList<>();
        /**
         * 表头数据（存储所有的表头数据）
         */
        private final List<Map<Integer, String>> headList = new ArrayList<>();

        /**
         * 这里会一行行的返回头
         */
        @Override
        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
            //log.info("解析到一条头数据:{}", JSON.toJSONString(headMap));
            //存储全部表头数据
            headList.add(headMap);
        }

        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {

        }

        @Override
        public void invoke(T t, AnalysisContext analysisContext) {
            data.add(t);
        }

        public List<T> getResult() {
            return data;
        }

        public List<Map<Integer, String>> getHeadList() {
            return headList;
        }
    }
}
